package view.student;

import controller.SeatController;
import controller.ReservationController;
import model.User;
import model.Seat;
import model.Reservation;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * 座位预约面板 - 按用户需求重新设计
 */
public class SeatReservationPanel extends JPanel {
    private User currentUser;
    private SeatController seatController;
    private ReservationController reservationController;

    // 界面状态管理
    private boolean isFloorSelectionView = true;
    private int selectedFloor = -1;

    // 主要界面组件
    private CardLayout cardLayout;
    private JPanel mainPanel;
    private JPanel floorSelectionPanel;
    private JPanel seatSelectionPanel;

    // 座位选择界面组件
    private JLabel selectedFloorLabel;
    private JComboBox<String> dateComboBox;
    private Map<String, JCheckBox> timeSlotCheckBoxes;
    private JPanel seatGridPanel;
    private JButton reserveButton;
    private JButton backButton;

    // 选中的座位
    private JButton selectedSeatButton;
    private Seat selectedSeat;

    // 楼层配置
    private final Map<Integer, String> floorAddresses = new HashMap<>();
    private final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    public SeatReservationPanel(User user) {
        this.currentUser = user;
        this.seatController = new SeatController();
        this.reservationController = new ReservationController();

        initFloorAddresses();
        initComponents();
        setupLayout();
        loadFloorSelection();
    }

    /**
     * 初始化区域地址信息
     */
    private void initFloorAddresses() {
        floorAddresses.put(1, "学生宿舍A区1楼自习室");
        floorAddresses.put(2, "学生宿舍C区1楼自习室");
        floorAddresses.put(3, "图书馆1楼阅览室");
        floorAddresses.put(4, "图书馆2楼阅览室");
        floorAddresses.put(5, "图书馆3楼研讨室");
        floorAddresses.put(6, "第16教学楼2楼自习室");
        floorAddresses.put(7, "第3教学楼3楼自习室");
    }

    /**
     * 初始化组件
     */
    private void initComponents() {
        cardLayout = new CardLayout();
        mainPanel = new JPanel(cardLayout);

        // 初始化时间段选择框
        timeSlotCheckBoxes = new HashMap<>();
        timeSlotCheckBoxes.put("上午", new JCheckBox("上午 8:00-12:00"));
        timeSlotCheckBoxes.put("下午", new JCheckBox("下午 12:00-18:00"));
        timeSlotCheckBoxes.put("晚上", new JCheckBox("晚上 18:00-22:00"));

        // 美化复选框
        for (JCheckBox checkBox : timeSlotCheckBoxes.values()) {
            styleCheckBox(checkBox);
            checkBox.addActionListener(e -> handleTimeSlotSelection((JCheckBox) e.getSource()));
        }

        // 初始化日期选择框
        dateComboBox = new JComboBox<>();
        // 只添加今天和明天
        LocalDate today = LocalDate.now();
        dateComboBox.addItem(today.format(dateFormatter));
        dateComboBox.addItem(today.plusDays(1).format(dateFormatter));
        styleComboBox(dateComboBox);
        dateComboBox.addActionListener(_ -> updateSeatAvailability());

        // 其他组件
        selectedFloorLabel = new JLabel();
        selectedFloorLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 18));
        selectedFloorLabel.setForeground(new Color(55, 65, 81));

        reserveButton = new JButton("立即预约");
        styleButton(reserveButton, new Color(59, 130, 246), Color.WHITE);
        reserveButton.setEnabled(false);
        reserveButton.addActionListener(this::handleReservation);

        backButton = new JButton("返回");
        styleModernButton(backButton, new Color(99, 102, 241));
        backButton.addActionListener(_ -> showFloorSelection());

        seatGridPanel = new JPanel();
    }

    /**
     * 设置布局
     */
    private void setupLayout() {
        setLayout(new BorderLayout());
        setBackground(new Color(248, 250, 252));

        // 创建楼层选择面板
        createFloorSelectionPanel();

        // 创建座位选择面板
        createSeatSelectionPanel();

        // 添加到卡片布局
        mainPanel.add(floorSelectionPanel, "FLOOR_SELECTION");
        mainPanel.add(seatSelectionPanel, "SEAT_SELECTION");

        add(mainPanel, BorderLayout.CENTER);
    }

    /**
     * 创建楼层选择面板
     */
    private void createFloorSelectionPanel() {
        floorSelectionPanel = new JPanel(new BorderLayout());
        floorSelectionPanel.setBackground(new Color(248, 250, 252));

        // 顶部区域包含标题和统计信息
        JPanel headerPanel = createFloorSelectionHeader();
        floorSelectionPanel.add(headerPanel, BorderLayout.NORTH);

        // 中心区域：楼层网格卡片
        JPanel centerPanel = new JPanel(new BorderLayout());
        centerPanel.setBackground(new Color(248, 250, 252));
        centerPanel.setBorder(BorderFactory.createEmptyBorder(0, 40, 40, 40));

        // 楼层网格容器 - 使用GridBagLayout实现响应式布局
        JPanel floorGridContainer = new JPanel(new GridBagLayout());
        floorGridContainer.setBackground(new Color(248, 250, 252));

        JScrollPane scrollPane = new JScrollPane(floorGridContainer);
        scrollPane.setBorder(null);
        scrollPane.setBackground(new Color(248, 250, 252));
        scrollPane.getViewport().setBackground(new Color(248, 250, 252));
        scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

        centerPanel.add(scrollPane, BorderLayout.CENTER);
        floorSelectionPanel.add(centerPanel, BorderLayout.CENTER);
    }

    /**
     * 创建楼层选择页面的头部区域
     */
    private JPanel createFloorSelectionHeader() {
        JPanel headerPanel = new JPanel(new BorderLayout());
        headerPanel.setBackground(new Color(248, 250, 252));
        headerPanel.setBorder(BorderFactory.createEmptyBorder(30, 40, 20, 40));

        // 左侧：标题和副标题
        JPanel titlePanel = new JPanel();
        titlePanel.setLayout(new BoxLayout(titlePanel, BoxLayout.Y_AXIS));
        titlePanel.setBackground(new Color(248, 250, 252));

        JLabel titleLabel = new JLabel("自习室预约");
        titleLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 28));
        titleLabel.setForeground(new Color(55, 65, 81));
        titleLabel.setAlignmentX(Component.LEFT_ALIGNMENT);

        JLabel subtitleLabel = new JLabel("选择您要预约的学习区域");
        subtitleLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 16));
        subtitleLabel.setForeground(new Color(107, 114, 128));
        subtitleLabel.setBorder(BorderFactory.createEmptyBorder(8, 0, 0, 0));
        subtitleLabel.setAlignmentX(Component.LEFT_ALIGNMENT);

        titlePanel.add(titleLabel);
        titlePanel.add(subtitleLabel);

        // 右侧：实时统计信息
        JPanel statsPanel = createOverallStatsPanel();

        headerPanel.add(titlePanel, BorderLayout.WEST);
        headerPanel.add(statsPanel, BorderLayout.EAST);

        return headerPanel;
    }

    /**
     * 创建总体统计面板
     */
    private JPanel createOverallStatsPanel() {
        JPanel statsPanel = new JPanel(new GridLayout(2, 2, 15, 8));
        statsPanel.setBackground(Color.WHITE);
        statsPanel.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createLineBorder(new Color(229, 231, 235), 1),
                BorderFactory.createEmptyBorder(20, 25, 20, 25)));

        // 获取总体统计数据
        int[] stats = getOverallStats();

        // 总座位数
        JPanel totalPanel = createStatItem("总座位", String.valueOf(stats[0]), new Color(99, 102, 241));
        // 可用座位数
        JPanel availablePanel = createStatItem("可用", String.valueOf(stats[1]), new Color(34, 197, 94));
        // 已预约座位数
        JPanel reservedPanel = createStatItem("已约", String.valueOf(stats[2]), new Color(245, 101, 101));
        // 维修座位数
        JPanel maintenancePanel = createStatItem("维修", String.valueOf(stats[3]), new Color(156, 163, 175));

        statsPanel.add(totalPanel);
        statsPanel.add(availablePanel);
        statsPanel.add(reservedPanel);
        statsPanel.add(maintenancePanel);

        return statsPanel;
    }

    /**
     * 创建统计项
     */
    private JPanel createStatItem(String label, String value, Color color) {
        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
        panel.setBackground(Color.WHITE);

        JLabel valueLabel = new JLabel(value);
        valueLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 20));
        valueLabel.setForeground(color);
        valueLabel.setAlignmentX(Component.CENTER_ALIGNMENT);

        JLabel labelText = new JLabel(label);
        labelText.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
        labelText.setForeground(new Color(107, 114, 128));
        labelText.setAlignmentX(Component.CENTER_ALIGNMENT);

        panel.add(valueLabel);
        panel.add(Box.createVerticalStrut(4));
        panel.add(labelText);

        return panel;
    }

    /**
     * 获取总体统计数据
     */
    private int[] getOverallStats() {
        try {
            LocalDate today = LocalDate.now();
            java.sql.Date date = java.sql.Date.valueOf(today);
            LocalTime now = LocalTime.now();

            java.sql.Time startTime, endTime;
            if (now.isBefore(LocalTime.of(12, 0))) {
                startTime = java.sql.Time.valueOf("08:00:00");
                endTime = java.sql.Time.valueOf("12:00:00");
            } else if (now.isBefore(LocalTime.of(18, 0))) {
                startTime = java.sql.Time.valueOf("12:00:00");
                endTime = java.sql.Time.valueOf("18:00:00");
            } else {
                startTime = java.sql.Time.valueOf("18:00:00");
                endTime = java.sql.Time.valueOf("22:00:00");
            }

            List<Seat> allSeats = seatController.getAllSeatsWithStatus(date, startTime, endTime);

            int total = allSeats.size();
            int available = (int) allSeats.stream().filter(seat -> seat.getStatus() == 0).count();
            int reserved = (int) allSeats.stream().filter(seat -> seat.getStatus() == 1).count();
            int maintenance = (int) allSeats.stream().filter(seat -> seat.getStatus() == 2).count();

            return new int[] { total, available, reserved, maintenance };
        } catch (Exception e) {
            return new int[] { 0, 0, 0, 0 };
        }
    }

    /**
     * 创建座位选择面板
     */
    private void createSeatSelectionPanel() {
        seatSelectionPanel = new JPanel(new BorderLayout());
        seatSelectionPanel.setBackground(new Color(248, 250, 252));

        // 顶部信息面板
        JPanel topPanel = createTopPanel();
        seatSelectionPanel.add(topPanel, BorderLayout.NORTH);

        // 中部座位区域
        JScrollPane seatScrollPane = new JScrollPane(seatGridPanel);
        seatScrollPane.setBackground(Color.WHITE);
        seatScrollPane.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createEmptyBorder(20, 40, 20, 40),
                BorderFactory.createLineBorder(new Color(229, 231, 235), 1)));
        seatScrollPane.setPreferredSize(new Dimension(0, 400));
        seatSelectionPanel.add(seatScrollPane, BorderLayout.CENTER);

        // 底部按钮面板
        JPanel bottomPanel = createBottomPanel();
        seatSelectionPanel.add(bottomPanel, BorderLayout.SOUTH);
    }

    /**
     * 创建座位选择页面顶部面板
     */
    private JPanel createTopPanel() {
        JPanel topPanel = new JPanel(new BorderLayout());
        topPanel.setBackground(Color.WHITE);
        topPanel.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(229, 231, 235)),
                BorderFactory.createEmptyBorder(20, 40, 20, 40)));

        // 楼层标题和返回按钮
        JPanel headerPanel = new JPanel(new BorderLayout());
        headerPanel.setBackground(Color.WHITE);
        headerPanel.add(selectedFloorLabel, BorderLayout.WEST);
        headerPanel.add(backButton, BorderLayout.EAST);

        // 预约控制面板
        JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 20, 10));
        controlPanel.setBackground(Color.WHITE);

        // 预约日期
        controlPanel.add(createStyledLabel("预约日期"));
        controlPanel.add(dateComboBox);

        controlPanel.add(Box.createHorizontalStrut(20));

        // 预约时间
        controlPanel.add(createStyledLabel("预约时间"));
        for (String timeSlot : new String[] { "上午", "下午", "晚上" }) {
            controlPanel.add(timeSlotCheckBoxes.get(timeSlot));
        }

        topPanel.add(headerPanel, BorderLayout.NORTH);
        topPanel.add(controlPanel, BorderLayout.CENTER);

        // 座位状态说明
        JPanel legendPanel = createSeatLegend();
        topPanel.add(legendPanel, BorderLayout.SOUTH);

        return topPanel;
    }

    /**
     * 创建底部面板
     */
    private JPanel createBottomPanel() {
        JPanel bottomPanel = new JPanel(new BorderLayout());
        bottomPanel.setBackground(Color.WHITE);
        bottomPanel.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createMatteBorder(1, 0, 0, 0, new Color(229, 231, 235)),
                BorderFactory.createEmptyBorder(20, 40, 30, 40)));

        // 预约信息
        JPanel infoPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        infoPanel.setBackground(Color.WHITE);

        JLabel infoLabel = new JLabel("预约地点：");
        infoLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
        infoLabel.setForeground(new Color(107, 114, 128));
        infoPanel.add(infoLabel);

        JLabel locationLabel = new JLabel();
        locationLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 14));
        locationLabel.setForeground(new Color(55, 65, 81));
        infoPanel.add(locationLabel);

        // 预约按钮
        reserveButton.setPreferredSize(new Dimension(150, 45));

        bottomPanel.add(infoPanel, BorderLayout.WEST);
        bottomPanel.add(reserveButton, BorderLayout.EAST);

        return bottomPanel;
    }

    /**
     * 加载楼层选择界面
     */
    private void loadFloorSelection() {
        // 获取楼层网格容器
        JPanel centerPanel = (JPanel) floorSelectionPanel.getComponent(1);
        JScrollPane scrollPane = (JScrollPane) centerPanel.getComponent(0);
        JPanel floorGridContainer = (JPanel) scrollPane.getViewport().getView();

        floorGridContainer.removeAll();

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(15, 15, 15, 15);
        gbc.fill = GridBagConstraints.BOTH;
        gbc.weightx = 1.0;
        gbc.weighty = 1.0;

        // 创建3列3行的网格布局来放置7个区域
        int cols = 3;
        int rows = 3;

        for (int area = 1; area <= 7; area++) {
            int row = (area - 1) / cols;
            int col = (area - 1) % cols;

            gbc.gridx = col;
            gbc.gridy = row;

            // 如果是第三行的第一个卡片，让它居中
            if (area == 7) {
                gbc.gridx = 1; // 居中显示
            }

            JPanel areaCard = createCompactFloorCard(area);
            floorGridContainer.add(areaCard, gbc);
        }

        // 添加弹性空间，确保卡片靠上显示
        gbc.gridx = 0;
        gbc.gridy = rows;
        gbc.gridwidth = cols;
        gbc.weighty = 10.0; // 给底部更大的权重
        floorGridContainer.add(Box.createVerticalGlue(), gbc);

        floorGridContainer.revalidate();
        floorGridContainer.repaint();

        // 同时更新统计信息
        updateOverallStats();
    }

    /**
     * 更新总体统计信息
     */
    private void updateOverallStats() {
        // 找到头部面板中的统计面板并更新
        try {
            JPanel headerPanel = (JPanel) floorSelectionPanel.getComponent(0);
            JPanel statsPanel = (JPanel) headerPanel.getComponent(1);

            int[] stats = getOverallStats();

            for (int i = 0; i < 4; i++) {
                JPanel statItem = (JPanel) statsPanel.getComponent(i);
                JLabel valueLabel = (JLabel) statItem.getComponent(0);
                valueLabel.setText(String.valueOf(stats[i]));
            }

            statsPanel.revalidate();
            statsPanel.repaint();
        } catch (Exception e) {
            // 忽略更新错误
        }
    }

    /**
     * 创建紧凑型楼层卡片（适用于网格布局）
     */
    private JPanel createCompactFloorCard(int floor) {
        JPanel card = new JPanel();
        card.setLayout(new BoxLayout(card, BoxLayout.Y_AXIS));
        card.setBackground(Color.WHITE);
        card.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createLineBorder(new Color(229, 231, 235), 1),
                BorderFactory.createEmptyBorder(25, 20, 25, 20)));
        card.setPreferredSize(new Dimension(280, 200));
        card.setMinimumSize(new Dimension(250, 180));

        // 楼层名称（大标题）
        JLabel nameLabel = new JLabel(getFloorDisplayName(floor));
        nameLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 22));
        nameLabel.setForeground(new Color(55, 65, 81));
        nameLabel.setAlignmentX(Component.CENTER_ALIGNMENT);

        // 地址信息
        String address = floorAddresses.get(floor);
        JLabel addressLabel = new JLabel("<html><center>" + address + "</center></html>");
        addressLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 13));
        addressLabel.setForeground(new Color(107, 114, 128));
        addressLabel.setAlignmentX(Component.CENTER_ALIGNMENT);

        // 座位可用性状态
        JPanel statusPanel = createFloorStatusPanel(floor);
        statusPanel.setAlignmentX(Component.CENTER_ALIGNMENT);

        // 选座按钮
        JButton selectButton = new JButton();
        boolean hasAvailableSeats = isFloorHasAvailableSeats(floor);

        if (!hasAvailableSeats) {
            selectButton.setText("已满");
            selectButton.setEnabled(false);
            styleCompactButton(selectButton, new Color(156, 163, 175), Color.WHITE);
        } else {
            selectButton.setText("选座");
            styleCompactButton(selectButton, new Color(59, 130, 246), Color.WHITE);
            selectButton.addActionListener(_ -> showSeatSelection(floor));

            // 添加悬停效果
            selectButton.addMouseListener(new java.awt.event.MouseAdapter() {
                @Override
                public void mouseEntered(java.awt.event.MouseEvent e) {
                    if (selectButton.isEnabled()) {
                        selectButton.setBackground(new Color(37, 99, 235));
                    }
                }

                @Override
                public void mouseExited(java.awt.event.MouseEvent e) {
                    if (selectButton.isEnabled()) {
                        selectButton.setBackground(new Color(59, 130, 246));
                    }
                }
            });
        }

        selectButton.setMaximumSize(new Dimension(120, 36));
        selectButton.setAlignmentX(Component.CENTER_ALIGNMENT);

        // 组装卡片
        card.add(nameLabel);
        card.add(Box.createVerticalStrut(8));
        card.add(addressLabel);
        card.add(Box.createVerticalStrut(15));
        card.add(statusPanel);
        card.add(Box.createVerticalGlue()); // 弹性空间
        card.add(selectButton);

        // 卡片点击效果
        addCardHoverEffect(card);

        return card;
    }

    /**
     * 创建楼层状态面板（显示座位统计）
     */
    private JPanel createFloorStatusPanel(int floor) {
        JPanel statusPanel = new JPanel(new GridLayout(2, 2, 10, 5));
        statusPanel.setBackground(Color.WHITE);
        statusPanel.setMaximumSize(new Dimension(200, 60));

        // 获取该楼层的座位统计
        int[] floorStats = getFloorStats(floor);

        // 可用座位
        JPanel availablePanel = createMiniStatItem("可用", String.valueOf(floorStats[0]), new Color(34, 197, 94));
        // 已预约座位
        JPanel reservedPanel = createMiniStatItem("已约", String.valueOf(floorStats[1]), new Color(245, 101, 101));
        // 维修座位
        JPanel maintenancePanel = createMiniStatItem("维修", String.valueOf(floorStats[2]), new Color(156, 163, 175));
        // 总座位
        JPanel totalPanel = createMiniStatItem("总计", String.valueOf(floorStats[3]), new Color(99, 102, 241));

        statusPanel.add(availablePanel);
        statusPanel.add(reservedPanel);
        statusPanel.add(maintenancePanel);
        statusPanel.add(totalPanel);

        return statusPanel;
    }

    /**
     * 创建迷你统计项
     */
    private JPanel createMiniStatItem(String label, String value, Color color) {
        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
        panel.setBackground(Color.WHITE);

        // 彩色指示点
        JPanel colorDot = new JPanel();
        colorDot.setBackground(color);
        colorDot.setPreferredSize(new Dimension(8, 8));
        colorDot.setMaximumSize(new Dimension(8, 8));
        colorDot.setBorder(BorderFactory.createEmptyBorder());

        JLabel valueLabel = new JLabel(value);
        valueLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 14));
        valueLabel.setForeground(color);

        JLabel labelText = new JLabel(label);
        labelText.setFont(new Font("Microsoft YaHei", Font.PLAIN, 11));
        labelText.setForeground(new Color(107, 114, 128));

        panel.add(colorDot);
        panel.add(Box.createHorizontalStrut(6));
        panel.add(valueLabel);
        panel.add(Box.createHorizontalStrut(4));
        panel.add(labelText);
        panel.add(Box.createHorizontalGlue());

        return panel;
    }

    /**
     * 获取楼层统计数据
     */
    private int[] getFloorStats(int floor) {
        try {
            LocalDate today = LocalDate.now();
            java.sql.Date date = java.sql.Date.valueOf(today);
            LocalTime now = LocalTime.now();

            java.sql.Time startTime, endTime;
            if (now.isBefore(LocalTime.of(12, 0))) {
                startTime = java.sql.Time.valueOf("08:00:00");
                endTime = java.sql.Time.valueOf("12:00:00");
            } else if (now.isBefore(LocalTime.of(18, 0))) {
                startTime = java.sql.Time.valueOf("12:00:00");
                endTime = java.sql.Time.valueOf("18:00:00");
            } else {
                startTime = java.sql.Time.valueOf("18:00:00");
                endTime = java.sql.Time.valueOf("22:00:00");
            }

            List<Seat> floorSeats = seatController.getSeatsByFloorWithStatus(floor, date, startTime, endTime);

            int available = (int) floorSeats.stream().filter(seat -> seat.getStatus() == 0).count();
            int reserved = (int) floorSeats.stream().filter(seat -> seat.getStatus() == 1).count();
            int maintenance = (int) floorSeats.stream().filter(seat -> seat.getStatus() == 2).count();
            int total = floorSeats.size();

            return new int[] { available, reserved, maintenance, total };
        } catch (Exception e) {
            return new int[] { 0, 0, 0, 0 };
        }
    }

    /**
     * 检查楼层是否有可用座位
     */
    private boolean isFloorHasAvailableSeats(int floor) {
        int[] stats = getFloorStats(floor);
        return stats[0] > 0; // available > 0
    }

    /**
     * 添加卡片悬停效果
     */
    private void addCardHoverEffect(JPanel card) {
        Color originalBg = card.getBackground();
        Color hoverBg = new Color(249, 250, 251);

        card.addMouseListener(new java.awt.event.MouseAdapter() {
            @Override
            public void mouseEntered(java.awt.event.MouseEvent e) {
                card.setBackground(hoverBg);
                card.setBorder(BorderFactory.createCompoundBorder(
                        BorderFactory.createLineBorder(new Color(59, 130, 246), 1),
                        BorderFactory.createEmptyBorder(25, 20, 25, 20)));
                card.setCursor(new Cursor(Cursor.HAND_CURSOR));
            }

            @Override
            public void mouseExited(java.awt.event.MouseEvent e) {
                card.setBackground(originalBg);
                card.setBorder(BorderFactory.createCompoundBorder(
                        BorderFactory.createLineBorder(new Color(229, 231, 235), 1),
                        BorderFactory.createEmptyBorder(25, 20, 25, 20)));
                card.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
            }
        });
    }

    /**
     * 紧凑按钮样式
     */
    private void styleCompactButton(JButton button, Color backgroundColor, Color textColor) {
        button.setBackground(backgroundColor);
        button.setForeground(textColor);
        button.setFont(new Font("Microsoft YaHei", Font.BOLD, 14));
        button.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createLineBorder(backgroundColor.darker(), 1),
                BorderFactory.createEmptyBorder(8, 20, 8, 20)));
        button.setFocusPainted(false);
        button.setCursor(new Cursor(Cursor.HAND_CURSOR));
        button.setOpaque(true);
        button.setContentAreaFilled(true);
    }

    /*
     * 创建原版楼层卡片（已弃用，保留以防需要）
     * 
     * private JPanel createFloorCard(int floor) {
     * // ... 原代码已注释
     * return null;
     * }
     */

    /**
     * 获取区域显示名称
     */
    private String getFloorDisplayName(int areaId) {
        switch (areaId) {
            case 1:
                return "A区宿舍自习室";
            case 2:
                return "C区宿舍自习室";
            case 3:
                return "图书馆一层";
            case 4:
                return "图书馆二层";
            case 5:
                return "图书馆三层";
            case 6:
                return "第16教学楼自习室";
            case 7:
                return "第3教学楼自习室";
            default:
                return "未知区域" + areaId;
        }
    }

    /*
     * 获取楼层可用性标签（已弃用，功能已被 getFloorStats 替代）
     *
     * private JLabel getFloorAvailabilityLabel(int floor) {
     * // ... 原代码已注释
     * return null;
     * }
     */

    /**
     * 显示座位选择界面
     */
    private void showSeatSelection(int area) {
        selectedFloor = area;
        selectedFloorLabel.setText(getFloorDisplayName(area));

        // 更新底部地址信息
        updateBottomLocationInfo();

        // 重置选择
        selectedSeat = null;
        selectedSeatButton = null;
        reserveButton.setEnabled(false);

        // 根据当前时间自动选择时间段
        selectDefaultTimeSlot();

        // 更新座位可用性
        updateSeatAvailability();

        cardLayout.show(mainPanel, "SEAT_SELECTION");
        isFloorSelectionView = false;
    }

    /**
     * 显示楼层选择界面
     */
    private void showFloorSelection() {
        cardLayout.show(mainPanel, "FLOOR_SELECTION");
        isFloorSelectionView = true;
        loadFloorSelection(); // 刷新楼层信息
    }

    /**
     * 处理时间段选择
     */
    private void handleTimeSlotSelection(JCheckBox checkBox) {
        if (checkBox.isSelected()) {
            // 获取当前选择的日期
            String selectedDate = (String) dateComboBox.getSelectedItem();
            if (selectedDate == null) {
                checkBox.setSelected(false);
                return;
            }

            LocalDate date = LocalDate.parse(selectedDate, dateFormatter);
            LocalDate today = LocalDate.now();

            // 如果是今天，需要检查时间段是否已过期
            if (date.equals(today)) {
                LocalTime now = LocalTime.now();
                String timeSlotKey = getTimeSlotKey(checkBox);
                LocalTime[] timeRange = getTimeSlotRange(timeSlotKey);

                if (timeRange != null && now.isAfter(timeRange[1])) {
                    // 时间段已过期
                    checkBox.setSelected(false);
                    String timeSlotText = checkBox.getText();
                    JOptionPane.showMessageDialog(this,
                            "无法选择已过期的时间段！\n\n" +
                                    "当前时间段 [" + timeSlotText + "] 已结束，\n" +
                                    "请选择其他时间段或预约明天的座位。",
                            "时间段已过期", JOptionPane.WARNING_MESSAGE);
                    return;
                }
            }
        }

        // 更新座位可用性
        updateSeatAvailability();
    }

    /**
     * 获取时间段对应的键值
     */
    private String getTimeSlotKey(JCheckBox checkBox) {
        for (Map.Entry<String, JCheckBox> entry : timeSlotCheckBoxes.entrySet()) {
            if (entry.getValue() == checkBox) {
                return entry.getKey();
            }
        }
        return null;
    }

    /**
     * 获取时间段的开始和结束时间
     */
    private LocalTime[] getTimeSlotRange(String timeSlotKey) {
        if (timeSlotKey == null)
            return null;

        switch (timeSlotKey) {
            case "上午":
                return new LocalTime[] { LocalTime.of(8, 0), LocalTime.of(12, 0) };
            case "下午":
                return new LocalTime[] { LocalTime.of(12, 0), LocalTime.of(18, 0) };
            case "晚上":
                return new LocalTime[] { LocalTime.of(18, 0), LocalTime.of(22, 0) };
            default:
                return null;
        }
    }

    /**
     * 更新座位可用性
     */
    private void updateSeatAvailability() {
        if (selectedFloor == -1)
            return;

        seatGridPanel.removeAll();

        try {
            String selectedDate = (String) dateComboBox.getSelectedItem();
            if (selectedDate == null)
                return;

            LocalDate date = LocalDate.parse(selectedDate, dateFormatter);
            List<java.sql.Time[]> timeRanges = getSelectedTimeRanges();

            if (timeRanges.isEmpty()) {
                // 没有选中时间段，显示提示
                showNoTimeSelectedMessage();
                return;
            }

            // 获取该楼层所有座位，并检查在所有选中时间段的可用性
            List<Seat> finalSeats = getSeatAvailabilityForAllTimeSlots(selectedFloor, date, timeRanges);

            // 根据效果图，创建座位网格布局
            createSeatGrid(finalSeats);

        } catch (Exception e) {
            showErrorMessage("加载座位信息失败: " + e.getMessage());
        }

        seatGridPanel.revalidate();
        seatGridPanel.repaint();
    }

    /**
     * 获取选中的时间段范围
     */
    private List<java.sql.Time[]> getSelectedTimeRanges() {
        List<java.sql.Time[]> ranges = new ArrayList<>();

        if (timeSlotCheckBoxes.get("上午").isSelected()) {
            ranges.add(new java.sql.Time[] {
                    java.sql.Time.valueOf("08:00:00"),
                    java.sql.Time.valueOf("12:00:00")
            });
        }
        if (timeSlotCheckBoxes.get("下午").isSelected()) {
            ranges.add(new java.sql.Time[] {
                    java.sql.Time.valueOf("12:00:00"),
                    java.sql.Time.valueOf("18:00:00")
            });
        }
        if (timeSlotCheckBoxes.get("晚上").isSelected()) {
            ranges.add(new java.sql.Time[] {
                    java.sql.Time.valueOf("18:00:00"),
                    java.sql.Time.valueOf("22:00:00")
            });
        }

        return ranges;
    }

    /**
     * 获取座位在所有选中时间段的可用性状态
     * 只有在所有时间段都可用的座位才标记为可用
     */
    private List<Seat> getSeatAvailabilityForAllTimeSlots(int floor, LocalDate date, List<java.sql.Time[]> timeRanges) {
        try {
            if (timeRanges.isEmpty()) {
                return new ArrayList<>();
            }

            // 先获取第一个时间段的座位状态作为基础
            java.sql.Time[] firstRange = timeRanges.get(0);
            List<Seat> baseSeats = seatController.getSeatsByFloorWithStatus(floor,
                    java.sql.Date.valueOf(date), firstRange[0], firstRange[1]);

            // 如果只有一个时间段，直接返回
            if (timeRanges.size() == 1) {
                return baseSeats;
            }

            // 创建座位映射，便于查找
            Map<String, Seat> availableSeats = new HashMap<>();
            for (Seat seat : baseSeats) {
                if (seat.getStatus() == 0) { // 只保留可用座位
                    availableSeats.put(seat.getSeatNumber(), seat);
                }
            }

            // 检查其他时间段，移除在任何时间段不可用的座位
            for (int i = 1; i < timeRanges.size(); i++) {
                java.sql.Time[] range = timeRanges.get(i);
                List<Seat> seats = seatController.getSeatsByFloorWithStatus(floor,
                        java.sql.Date.valueOf(date), range[0], range[1]);

                // 创建当前时间段可用座位的集合
                Set<String> currentAvailableSeats = new HashSet<>();
                for (Seat seat : seats) {
                    if (seat.getStatus() == 0) {
                        currentAvailableSeats.add(seat.getSeatNumber());
                    }
                }

                // 移除在当前时间段不可用的座位
                availableSeats.entrySet().removeIf(entry -> !currentAvailableSeats.contains(entry.getKey()));
            }

            // 构建最终结果：包含所有座位，但只有在所有时间段都可用的座位才标记为可用
            List<Seat> result = new ArrayList<>();
            Map<String, Seat> seatMap = new HashMap<>();
            for (Seat seat : baseSeats) {
                seatMap.put(seat.getSeatNumber(), seat);
            }

            for (Seat seat : baseSeats) {
                Seat finalSeat = new Seat();
                finalSeat.setSeatId(seat.getSeatId());
                finalSeat.setSeatNumber(seat.getSeatNumber());
                finalSeat.setFloor(seat.getFloor());
                finalSeat.setRoom(seat.getRoom());
                finalSeat.setSeatIndex(seat.getSeatIndex());
                finalSeat.setArea(seat.getArea());
                // 注意：这里使用基础状态，在后面会根据可用性重新设置
                finalSeat.setEquipment(seat.getEquipment());
                finalSeat.setHasComputer(seat.isHasComputer());
                finalSeat.setHasPowerSocket(seat.isHasPowerSocket());

                // 关键逻辑：只有在availableSeats中的座位才标记为可用
                if (availableSeats.containsKey(seat.getSeatNumber())) {
                    finalSeat.setStatus(0); // 可用
                } else {
                    finalSeat.setStatus(1); // 不可用
                }

                result.add(finalSeat);
            }

            return result;

        } catch (Exception e) {
            e.printStackTrace();
            return new ArrayList<>();
        }
    }

    /**
     * 创建楼层平面图布局
     */
    private void createSeatGrid(List<Seat> seats) {
        seatGridPanel.setLayout(new BorderLayout());
        seatGridPanel.setBackground(new Color(248, 250, 252));
        seatGridPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

        // 创建完整的楼层容器（包含楼层图和信息面板）
        JPanel completeFloorPanel = new JPanel();
        completeFloorPanel.setLayout(new BoxLayout(completeFloorPanel, BoxLayout.Y_AXIS));
        completeFloorPanel.setBackground(new Color(248, 250, 252));

        // 楼层平面图主面板
        JPanel floorPlanPanel = createFloorPlanLayout(selectedFloor, seats);
        completeFloorPanel.add(floorPlanPanel);

        // 删除图例面板，不再需要

        // 统一的滚动面板
        JScrollPane unifiedScrollPane = new JScrollPane(completeFloorPanel);
        unifiedScrollPane.setBorder(null);
        unifiedScrollPane.getViewport().setBackground(new Color(248, 250, 252));
        unifiedScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        unifiedScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);

        seatGridPanel.add(unifiedScrollPane, BorderLayout.CENTER);
    }

    /**
     * 创建楼层平面图布局
     */
    private JPanel createFloorPlanLayout(int floor, List<Seat> seats) {
        JPanel planPanel = new JPanel();
        planPanel.setLayout(null); // 使用绝对定位来精确控制位置
        planPanel.setBackground(Color.WHITE);
        planPanel.setPreferredSize(new Dimension(1000, 365));
        planPanel.setBorder(BorderFactory.createLineBorder(new Color(229, 231, 235), 2));

        Map<String, Seat> seatMap = new HashMap<>();
        for (Seat seat : seats) {
            seatMap.put(seat.getSeatNumber(), seat);
        }

        // 统一布局管理：所有元素在一个平面上精确定位
        createUnifiedFloorLayout(planPanel, seatMap, floor);

        return planPanel;
    }

    /* 旧的设施添加方法已被新的统一布局方法替代 */

    /**
     * 创建统一的楼层网格布局（所有按钮在网格中统一排列）
     */
    private void createUnifiedFloorLayout(JPanel planPanel, Map<String, Seat> seatMap, int floor) {
        // 使用网格布局管理所有按钮
        planPanel.setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(2, 2, 2, 2); // 统一间距

        // 创建网格布局：设施 + A房间 + 书架 + F房间 + 书架 + B房间 + 书架 + C房间 + 书架 + D房间 + 书架 + E房间 + 设施
        createGridLayout(planPanel, seatMap, gbc);
    }

    /**
     * 创建网格布局
     */
    private void createGridLayout(JPanel planPanel, Map<String, Seat> seatMap, GridBagConstraints gbc) {
        // 第一行：区域标签（最顶部）
        gbc.gridy = 0;
        addAreaLabels(planPanel, gbc);

        // 第二行：顶部设施
        gbc.gridy = 1;
        addTopFacilities(planPanel, gbc);

        // 第3-6行：主要内容区域（4行座位）
        for (int row = 0; row < 4; row++) {
            gbc.gridy = row + 2;
            addContentRow(planPanel, seatMap, gbc, row);
        }

        // 第7行：底部大通道（完整标签）
        gbc.gridy = 6;
        addBottomMainCorridor(planPanel, gbc);

        // 第8行：底部设施
        gbc.gridy = 7;
        addBottomFacilities(planPanel, gbc);
    }

    /**
     * 添加顶部设施行（标签形式）
     */
    private void addTopFacilities(JPanel planPanel, GridBagConstraints gbc) {
        String[] topFacilities = { "电梯1", "", "窗户", "窗户", "窗户", "窗户", "窗户", "", "窗户", "窗户", "窗户", "", "窗户", "窗户", "窗户",
                "窗户", "窗户", "窗户", "窗户", "", "安全梯" };
        Color[] topColors = {
                new Color(156, 163, 175), Color.LIGHT_GRAY,
                new Color(187, 247, 208), new Color(187, 247, 208), new Color(187, 247, 208), new Color(187, 247, 208),
                new Color(187, 247, 208), Color.LIGHT_GRAY,
                new Color(187, 247, 208), new Color(187, 247, 208), new Color(187, 247, 208), Color.LIGHT_GRAY,
                new Color(187, 247, 208), new Color(187, 247, 208), new Color(187, 247, 208), new Color(187, 247, 208),
                new Color(187, 247, 208), new Color(187, 247, 208), new Color(187, 247, 208),
                Color.LIGHT_GRAY, new Color(245, 101, 101)
        };

        for (int col = 0; col < topFacilities.length; col++) {
            gbc.gridx = col;
            if (!topFacilities[col].isEmpty()) {
                addFacilityLabel(planPanel, topFacilities[col], gbc, topColors[col]);
            } else {
                addEmptyCell(planPanel, gbc);
            }
        }
    }

    /**
     * 添加设施标签（与区域标签样式一致）
     */
    private void addFacilityLabel(JPanel planPanel, String text, GridBagConstraints gbc, Color bgColor) {
        JLabel label = new JLabel(text, JLabel.CENTER);
        label.setPreferredSize(new Dimension(35, 25));
        label.setBackground(bgColor);
        label.setForeground(Color.WHITE);
        label.setFont(new Font("Microsoft YaHei", Font.BOLD, 9));
        label.setBorder(BorderFactory.createLineBorder(bgColor.darker(), 1));
        label.setOpaque(true);

        planPanel.add(label, gbc);
    }

    /**
     * 添加区域标签行
     */
    private void addAreaLabels(JPanel planPanel, GridBagConstraints gbc) {
        for (int col = 0; col < 21; col++) {
            gbc.gridx = col;

            if (col >= 2 && col <= 3) { // A区
                if (col == 2) {
                    gbc.gridwidth = 2;
                    addAreaLabel(planPanel, "A区自习室", gbc, new Color(99, 102, 241));
                    gbc.gridwidth = 1;
                }
            } else if (col >= 5 && col <= 6) { // F区
                if (col == 5) {
                    gbc.gridwidth = 2;
                    addAreaLabel(planPanel, "F区自习室", gbc, new Color(99, 102, 241));
                    gbc.gridwidth = 1;
                }
            } else if (col >= 8 && col <= 9) { // B区
                if (col == 8) {
                    gbc.gridwidth = 2;
                    addAreaLabel(planPanel, "B区讨论室", gbc, new Color(34, 197, 94));
                    gbc.gridwidth = 1;
                }
            } else if (col >= 11 && col <= 12) { // C区
                if (col == 11) {
                    gbc.gridwidth = 2;
                    addAreaLabel(planPanel, "C区阅览室", gbc, new Color(245, 101, 101));
                    gbc.gridwidth = 1;
                }
            } else if (col >= 14 && col <= 15) { // D区
                if (col == 14) {
                    gbc.gridwidth = 2;
                    addAreaLabel(planPanel, "D区讨论室", gbc, new Color(34, 197, 94));
                    gbc.gridwidth = 1;
                }
            } else if (col >= 17 && col <= 18) { // E区
                if (col == 17) {
                    gbc.gridwidth = 2;
                    addAreaLabel(planPanel, "E区阅览室", gbc, new Color(245, 101, 101));
                    gbc.gridwidth = 1;
                }
            } else {
                addEmptyCell(planPanel, gbc);
            }
        }
    }

    /**
     * 添加区域标签
     */
    private void addAreaLabel(JPanel planPanel, String text, GridBagConstraints gbc, Color bgColor) {
        JLabel label = new JLabel(text, JLabel.CENTER);
        label.setPreferredSize(new Dimension(70, 25));
        label.setBackground(bgColor.brighter());
        label.setForeground(Color.WHITE);
        label.setFont(new Font("Microsoft YaHei", Font.BOLD, 10));
        label.setBorder(BorderFactory.createLineBorder(bgColor, 1));
        label.setOpaque(true);

        planPanel.add(label, gbc);
    }

    /**
     * 添加内容行（座位+书架+通道）
     */
    private void addContentRow(JPanel planPanel, Map<String, Seat> seatMap, GridBagConstraints gbc, int row) {
        // 计算每个房间在该行的座位编号
        int seatInRoom = row * 2; // 每行2个座位

        // 左侧设施（标签形式）
        gbc.gridx = 0;
        if (row == 0)
            addFacilityLabel(planPanel, "电梯2", gbc, new Color(156, 163, 175));
        else if (row == 1)
            addFacilityLabel(planPanel, "男厕", gbc, new Color(59, 130, 246));
        else if (row == 2)
            addFacilityLabel(planPanel, "女厕", gbc, new Color(219, 39, 119));
        else
            addEmptyCell(planPanel, gbc);

        gbc.gridx = 1;
        addEmptyCell(planPanel, gbc); // 间隔

        // A房间座位（2列）
        gbc.gridx = 2;
        addSeatButton(planPanel, seatMap, "A", seatInRoom + 1, gbc);
        gbc.gridx = 3;
        addSeatButton(planPanel, seatMap, "A", seatInRoom + 2, gbc);

        // A和F之间的大书架（只在第一行添加，跨4行）
        gbc.gridx = 4;
        if (row == 0) {
            gbc.gridheight = 4; // 跨4行
            addLargeBookshelf(planPanel, gbc);
            gbc.gridheight = 1; // 恢复默认
        } else {
            // 其他行跳过，因为书架已经占用了这个位置
        }

        // F房间座位（2列）
        gbc.gridx = 5;
        addSeatButton(planPanel, seatMap, "F", seatInRoom + 1, gbc);
        gbc.gridx = 6;
        addSeatButton(planPanel, seatMap, "F", seatInRoom + 2, gbc);

        // F和B之间的大通道（只在第一行添加，跨4行）
        gbc.gridx = 7;
        if (row == 0) {
            gbc.gridheight = 4; // 跨4行
            addLargeCorridor(planPanel, gbc);
            gbc.gridheight = 1; // 恢复默认
        } else {
            // 其他行跳过，因为通道已经占用了这个位置
        }

        // B房间座位（2列）
        gbc.gridx = 8;
        addSeatButton(planPanel, seatMap, "B", seatInRoom + 1, gbc);
        gbc.gridx = 9;
        addSeatButton(planPanel, seatMap, "B", seatInRoom + 2, gbc);

        // B和C之间的大书架（只在第一行添加，跨4行）
        gbc.gridx = 10;
        if (row == 0) {
            gbc.gridheight = 4; // 跨4行
            addLargeBookshelf(planPanel, gbc);
            gbc.gridheight = 1; // 恢复默认
        } else {
            // 其他行跳过，因为书架已经占用了这个位置
        }

        // C房间座位（2列）
        gbc.gridx = 11;
        addSeatButton(planPanel, seatMap, "C", seatInRoom + 1, gbc);
        gbc.gridx = 12;
        addSeatButton(planPanel, seatMap, "C", seatInRoom + 2, gbc);

        // C和D之间的大通道（只在第一行添加，跨4行）
        gbc.gridx = 13;
        if (row == 0) {
            gbc.gridheight = 4; // 跨4行
            addLargeCorridor(planPanel, gbc);
            gbc.gridheight = 1; // 恢复默认
        } else {
            // 其他行跳过，因为通道已经占用了这个位置
        }

        // D房间座位（2列）
        gbc.gridx = 14;
        addSeatButton(planPanel, seatMap, "D", seatInRoom + 1, gbc);
        gbc.gridx = 15;
        addSeatButton(planPanel, seatMap, "D", seatInRoom + 2, gbc);

        // D和E之间的大书架（只在第一行添加，跨4行）
        gbc.gridx = 16;
        if (row == 0) {
            gbc.gridheight = 4; // 跨4行
            addLargeBookshelf(planPanel, gbc);
            gbc.gridheight = 1; // 恢复默认
        } else {
            // 其他行跳过，因为书架已经占用了这个位置
        }

        // E房间座位（2列）
        gbc.gridx = 17;
        addSeatButton(planPanel, seatMap, "E", seatInRoom + 1, gbc);
        gbc.gridx = 18;
        addSeatButton(planPanel, seatMap, "E", seatInRoom + 2, gbc);

        gbc.gridx = 19;
        addEmptyCell(planPanel, gbc); // 间隔

        // 右侧设施（标签形式）
        gbc.gridx = 20;
        if (row == 0)
            addFacilityLabel(planPanel, "主楼梯", gbc, new Color(245, 101, 101));
        else if (row == 1)
            addFacilityLabel(planPanel, "饮水", gbc, new Color(16, 185, 129));
        else if (row == 2)
            addFacilityLabel(planPanel, "消防", gbc, new Color(220, 38, 38));
        else
            addEmptyCell(planPanel, gbc);
    }

    /**
     * 添加大书架（跨4行的单个标签）
     */
    private void addLargeBookshelf(JPanel planPanel, GridBagConstraints gbc) {
        JLabel bookshelf = new JLabel("书架", JLabel.CENTER);
        bookshelf.setPreferredSize(new Dimension(35, 200)); // 高度增加到200
        bookshelf.setBackground(new Color(139, 69, 19));
        bookshelf.setForeground(Color.WHITE);
        bookshelf.setFont(new Font("Microsoft YaHei", Font.BOLD, 14));
        bookshelf.setBorder(BorderFactory.createLineBorder(new Color(101, 50, 14), 1));
        bookshelf.setOpaque(true);

        planPanel.add(bookshelf, gbc);
    }

    /**
     * 添加大通道（跨4行的单个标签）
     */
    private void addLargeCorridor(JPanel planPanel, GridBagConstraints gbc) {
        JLabel corridor = new JLabel("通道", JLabel.CENTER);
        corridor.setPreferredSize(new Dimension(35, 200)); // 高度200
        corridor.setBackground(new Color(249, 250, 251));
        corridor.setForeground(new Color(107, 114, 128));
        corridor.setFont(new Font("Microsoft YaHei", Font.BOLD, 14));
        corridor.setBorder(BorderFactory.createLineBorder(new Color(229, 231, 235), 1));
        corridor.setOpaque(true);

        planPanel.add(corridor, gbc);
    }

    /**
     * 添加底部主通道（完整的大标签）
     */
    private void addBottomMainCorridor(JPanel planPanel, GridBagConstraints gbc) {
        for (int col = 0; col < 21; col++) {
            gbc.gridx = col;
            if (col == 2) { // 在第2列开始添加跨多列的主通道
                gbc.gridwidth = 17; // 跨17列（从col 2到col 18）
                JLabel mainCorridor = new JLabel("主通道", JLabel.CENTER);
                mainCorridor.setPreferredSize(new Dimension(595, 25)); // 宽度为17个标准按钮
                mainCorridor.setBackground(new Color(249, 250, 251));
                mainCorridor.setForeground(new Color(107, 114, 128));
                mainCorridor.setFont(new Font("Microsoft YaHei", Font.BOLD, 14));
                mainCorridor.setBorder(BorderFactory.createLineBorder(new Color(229, 231, 235), 2));
                mainCorridor.setOpaque(true);
                planPanel.add(mainCorridor, gbc);
                gbc.gridwidth = 1; // 恢复默认
                col = 18; // 跳过已占用的列
            } else if (col < 2 || col > 18) {
                addEmptyCell(planPanel, gbc);
            }
        }
    }

    /**
     * 添加底部设施（标签形式）
     */
    private void addBottomFacilities(JPanel planPanel, GridBagConstraints gbc) {
        for (int col = 0; col < 21; col++) {
            gbc.gridx = col;
            if (col == 10) { // 中央入口
                addFacilityLabel(planPanel, "入口", gbc, new Color(34, 197, 94));
            } else if (col >= 2 && col <= 18) {
                addFacilityLabel(planPanel, "窗户", gbc, new Color(187, 247, 208));
            } else {
                addEmptyCell(planPanel, gbc);
            }
        }
    }

    /**
     * 添加座位按钮到网格
     */
    private void addSeatButton(JPanel planPanel, Map<String, Seat> seatMap, String roomLetter, int seatNum,
            GridBagConstraints gbc) {
        // 根据选中的楼层生成区域代码
        String areaCode = getAreaCode(selectedFloor);

        // 生成座位编号：区域代码-房间字母+座位号(2位)
        // 例如：A-A01, C-B02, LIB1-C03等
        String seatNumber = areaCode + "-" + roomLetter + String.format("%02d", seatNum);

        Seat seat = seatMap.get(seatNumber);
        if (seat != null) {
            JButton seatButton = createSeatButton(seat);
            planPanel.add(seatButton, gbc);
        } else {
            // 如果数据库中没有该座位，添加空白单元格
            addEmptyCell(planPanel, gbc);
        }
    }

    /**
     * 根据区域ID获取区域代码
     */
    private String getAreaCode(int areaId) {
        switch (areaId) {
            case 1:
                return "A";
            case 2:
                return "C";
            case 3:
                return "LIB1";
            case 4:
                return "LIB2";
            case 5:
                return "LIB3";
            case 6:
                return "T16";
            case 7:
                return "T3";
            default:
                return "X";
        }
    }

    /* 已移除addGridButton方法，所有设施都使用addFacilityLabel标签形式 */

    /**
     * 添加空白单元格
     */
    private void addEmptyCell(JPanel planPanel, GridBagConstraints gbc) {
        JLabel empty = new JLabel();
        empty.setPreferredSize(new Dimension(35, 25));
        planPanel.add(empty, gbc);
    }

    /* 旧的设施添加方法已被新的网格布局替代 */

    /* 已删除未使用的创建学习室方法 */

    /* 已删除旧的座位布局方法 */

    /* 不再使用的不规则形状方法已删除 */

    /* 已删除未使用的通道和窗户方法，由新的统一布局管理 */

    /* 图例面板已删除，不再需要 */

    /* 已移除虚拟座位创建方法，现在直接使用真实数据库数据 */

    /**
     * 创建座位按钮
     */
    private JButton createSeatButton(Seat seat) {
        JButton button = new JButton();
        button.setPreferredSize(new Dimension(50, 50));
        button.setFont(new Font("Microsoft YaHei", Font.BOLD, 10));
        button.setFocusPainted(false);
        button.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));

        // 根据座位状态设置颜色 - 按照用户需求
        // 绿色：可选，灰色：不可选，蓝色：已选
        updateSeatButtonAppearance(button, seat, false);

        // 只有可选座位才能点击
        if (seat.getStatus() == 0) { // 可用座位
            button.addActionListener(_ -> selectSeat(button, seat));
        }

        // 设置座位编号显示
        button.setText(seat.getSeatNumber());

        return button;
    }

    /**
     * 更新座位按钮外观
     */
    private void updateSeatButtonAppearance(JButton button, Seat seat, boolean isSelected) {
        if (isSelected) {
            // 蓝色：已选
            button.setBackground(new Color(59, 130, 246));
            button.setForeground(Color.WHITE);
            button.setBorder(BorderFactory.createLineBorder(new Color(37, 99, 235), 2));
        } else {
            switch (seat.getStatus()) {
                case 0: // 可选 - 绿色
                    button.setBackground(new Color(34, 197, 94));
                    button.setForeground(Color.WHITE);
                    button.setBorder(BorderFactory.createLineBorder(new Color(22, 163, 74), 1));
                    button.setEnabled(true);
                    break;
                case 1: // 已预约 - 灰色（不可选）
                case 2: // 维修中 - 灰色（不可选）
                default:
                    button.setBackground(new Color(156, 163, 175));
                    button.setForeground(Color.WHITE);
                    button.setBorder(BorderFactory.createLineBorder(new Color(107, 114, 128), 1));
                    button.setEnabled(false);
                    break;
            }
        }

        button.setOpaque(true);
        button.setContentAreaFilled(true);
    }

    /**
     * 选择座位
     */
    private void selectSeat(JButton button, Seat seat) {
        // 恢复之前选中的座位样式
        if (selectedSeatButton != null && selectedSeat != null) {
            updateSeatButtonAppearance(selectedSeatButton, selectedSeat, false);
        }

        // 设置新选中的座位
        selectedSeatButton = button;
        selectedSeat = seat;
        updateSeatButtonAppearance(button, seat, true);

        // 启用预约按钮
        reserveButton.setEnabled(true);
    }

    /**
     * 处理预约
     */
    private void handleReservation(ActionEvent e) {
        if (selectedSeat == null)
            return;

        try {
            String selectedDate = (String) dateComboBox.getSelectedItem();
            LocalDate date = LocalDate.parse(selectedDate, dateFormatter);
            List<java.sql.Time[]> timeRanges = getSelectedTimeRanges();

            if (timeRanges.isEmpty()) {
                JOptionPane.showMessageDialog(this, "请选择预约时间段", "提示", JOptionPane.WARNING_MESSAGE);
                return;
            }

            // 检查时间段是否已开始（仅对今天的预约）
            LocalDate today = LocalDate.now();
            if (date.equals(today)) {
                LocalTime now = LocalTime.now();
                for (java.sql.Time[] range : timeRanges) {
                    LocalTime startTime = range[0].toLocalTime();
                    LocalTime endTime = range[1].toLocalTime();

                    // 如果当前时间在时间段内（已开始但未结束）
                    if (now.isAfter(startTime) && now.isBefore(endTime)) {
                        long minutesPassed = java.time.Duration.between(startTime, now).toMinutes();
                        long totalMinutes = java.time.Duration.between(startTime, endTime).toMinutes();
                        long remainingMinutes = totalMinutes - minutesPassed;

                        String timeSlotText = startTime.toString().substring(0, 5) + "-" +
                                endTime.toString().substring(0, 5);

                        int choice = JOptionPane.showConfirmDialog(this,
                                "当前时间段已开始！\n\n" +
                                        "时间段：[" + timeSlotText + "]\n" +
                                        "已开始：" + minutesPassed + " 分钟\n" +
                                        "剩余时长：" + remainingMinutes + " 分钟\n\n" +
                                        "您的实际使用时长将不足，确定要继续预约吗？",
                                "时间段已开始",
                                JOptionPane.YES_NO_OPTION,
                                JOptionPane.QUESTION_MESSAGE);

                        if (choice != JOptionPane.YES_OPTION) {
                            return; // 用户选择不预约
                        }
                    }
                }
            }

            // 先检查所有选中的时间段是否都空闲
            for (java.sql.Time[] range : timeRanges) {
                Reservation tempReservation = new Reservation(
                        currentUser.getUserId(),
                        selectedSeat.getSeatId(),
                        date,
                        range[0].toLocalTime(),
                        range[1].toLocalTime());

                // 检查时间冲突
                if (reservationController.hasTimeConflict(tempReservation)) {
                    String conflictTimeSlot = range[0].toString().substring(0, 5) + "-"
                            + range[1].toString().substring(0, 5);
                    JOptionPane.showMessageDialog(this,
                            "预约失败！\n时间段 " + conflictTimeSlot + " 已被预约，请重新选择时间段。",
                            "预约冲突", JOptionPane.WARNING_MESSAGE);
                    return;
                }
            }

            // 如果所有时间段都空闲，则创建所有预约
            boolean allSuccess = true;
            String failMessage = "";
            for (java.sql.Time[] range : timeRanges) {
                Reservation reservation = new Reservation(
                        currentUser.getUserId(),
                        selectedSeat.getSeatId(),
                        date,
                        range[0].toLocalTime(),
                        range[1].toLocalTime());

                ReservationController.ReservationResult result = reservationController.makeReservation(reservation);
                if (!result.isSuccess()) {
                    allSuccess = false;
                    failMessage = result.getMessage();
                    break;
                }
            }

            if (allSuccess) {
                String timeSlotText = timeRanges.size() == 1 ? "时间段" : (timeRanges.size() + "个时间段");
                JOptionPane.showMessageDialog(this,
                        "预约成功！\n成功预约 " + timeSlotText + "，请按时到达座位。",
                        "预约成功", JOptionPane.INFORMATION_MESSAGE);
                updateSeatAvailability(); // 刷新座位状态

                // 重置选择
                selectedSeat = null;
                selectedSeatButton = null;
                reserveButton.setEnabled(false);
            } else {
                JOptionPane.showMessageDialog(this,
                        failMessage,
                        "预约失败", JOptionPane.WARNING_MESSAGE);
            }

        } catch (Exception ex) {
            JOptionPane.showMessageDialog(this, "预约失败: " + ex.getMessage(),
                    "错误", JOptionPane.ERROR_MESSAGE);
        }
    }

    /**
     * 更新底部位置信息
     */
    private void updateBottomLocationInfo() {
        JPanel bottomPanel = (JPanel) seatSelectionPanel.getComponent(2);
        JPanel infoPanel = (JPanel) bottomPanel.getComponent(0);

        if (infoPanel.getComponentCount() > 1) {
            JLabel locationLabel = (JLabel) infoPanel.getComponent(1);
            locationLabel.setText(getFloorDisplayName(selectedFloor));
        }
    }

    /**
     * 显示无时间选择提示
     */
    private void showNoTimeSelectedMessage() {
        seatGridPanel.setLayout(new BorderLayout());
        JLabel messageLabel = new JLabel("请选择预约时间段", JLabel.CENTER);
        messageLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 16));
        messageLabel.setForeground(new Color(107, 114, 128));
        seatGridPanel.add(messageLabel, BorderLayout.CENTER);
    }

    /**
     * 显示错误信息
     */
    private void showErrorMessage(String message) {
        seatGridPanel.setLayout(new BorderLayout());
        JLabel errorLabel = new JLabel(message, JLabel.CENTER);
        errorLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 16));
        errorLabel.setForeground(new Color(220, 38, 38));
        seatGridPanel.add(errorLabel, BorderLayout.CENTER);
    }

    /**
     * 创建座位状态说明
     */
    private JPanel createSeatLegend() {
        JPanel legendPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 15, 10));
        legendPanel.setBackground(Color.WHITE);

        // 蓝色：已选
        legendPanel.add(createLegendItem("已选", new Color(59, 130, 246)));
        // 绿色：可选
        legendPanel.add(createLegendItem("可选", new Color(34, 197, 94)));
        // 灰色：不可选
        legendPanel.add(createLegendItem("不可选", new Color(156, 163, 175)));

        return legendPanel;
    }

    /**
     * 创建图例项
     */
    private JComponent createLegendItem(String text, Color color) {
        JPanel item = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0));
        item.setBackground(Color.WHITE);

        JPanel colorBox = new JPanel();
        colorBox.setBackground(color);
        colorBox.setPreferredSize(new Dimension(20, 15));
        colorBox.setBorder(BorderFactory.createLineBorder(color.darker(), 1));

        JLabel label = new JLabel(text);
        label.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
        label.setForeground(new Color(75, 85, 99));

        item.add(colorBox);
        item.add(label);

        return item;
    }

    /**
     * 创建样式化标签
     */
    private JLabel createStyledLabel(String text) {
        JLabel label = new JLabel(text);
        label.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
        label.setForeground(new Color(75, 85, 99));
        return label;
    }

    /**
     * 现代化按钮样式（与统计页面一致）
     */
    private void styleModernButton(JButton button, Color backgroundColor) {
        button.setPreferredSize(new Dimension(90, 38));
        button.setBackground(backgroundColor);
        button.setForeground(Color.WHITE);
        button.setFont(new Font("Microsoft YaHei", Font.BOLD, 14));
        button.setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 20));
        button.setFocusPainted(false);
        button.setCursor(new Cursor(Cursor.HAND_CURSOR));
        button.setOpaque(true);
        button.setContentAreaFilled(true);

        // 悬停效果
        button.addMouseListener(new java.awt.event.MouseAdapter() {
            @Override
            public void mouseEntered(java.awt.event.MouseEvent evt) {
                if (button.isEnabled()) {
                    button.setBackground(backgroundColor.darker());
                }
            }

            @Override
            public void mouseExited(java.awt.event.MouseEvent evt) {
                if (button.isEnabled()) {
                    button.setBackground(backgroundColor);
                }
            }
        });
    }

    /**
     * 美化按钮样式
     */
    private void styleButton(JButton button, Color backgroundColor, Color textColor) {
        button.setBackground(backgroundColor);
        button.setForeground(textColor);
        button.setFont(new Font("Microsoft YaHei", Font.PLAIN, 13));
        button.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createLineBorder(backgroundColor.darker(), 1),
                BorderFactory.createEmptyBorder(8, 16, 8, 16)));
        button.setFocusPainted(false);
        button.setCursor(new Cursor(Cursor.HAND_CURSOR));
        button.setOpaque(true);
        button.setContentAreaFilled(true);
    }

    /**
     * 美化复选框样式
     */
    private void styleCheckBox(JCheckBox checkBox) {
        checkBox.setFont(new Font("Microsoft YaHei", Font.PLAIN, 13));
        checkBox.setForeground(new Color(75, 85, 99));
        checkBox.setBackground(Color.WHITE);
        checkBox.setFocusPainted(false);
    }

    /**
     * 美化组合框样式
     */
    private void styleComboBox(JComboBox<String> comboBox) {
        comboBox.setPreferredSize(new Dimension(150, 30));
        comboBox.setFont(new Font("Microsoft YaHei", Font.PLAIN, 13));
        comboBox.setBackground(Color.WHITE);
        comboBox.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createLineBorder(new Color(209, 213, 219), 1),
                BorderFactory.createEmptyBorder(4, 8, 4, 8)));
    }

    /**
     * 根据当前时间自动选择默认时间段
     */
    private void selectDefaultTimeSlot() {
        // 先清空所有选择
        for (JCheckBox checkBox : timeSlotCheckBoxes.values()) {
            checkBox.setSelected(false);
        }

        LocalTime currentTime = LocalTime.now();
        String selectedDateStr = (String) dateComboBox.getSelectedItem();
        LocalDate selectedDate = LocalDate.parse(selectedDateStr, dateFormatter);
        LocalDate today = LocalDate.now();

        // 如果选择的是今天，需要根据当前时间选择合适的时间段
        if (selectedDate.equals(today)) {
            if (currentTime.isBefore(LocalTime.of(12, 0))) {
                // 当前时间在12点之前，选择上午
                timeSlotCheckBoxes.get("上午").setSelected(true);
            } else if (currentTime.isBefore(LocalTime.of(18, 0))) {
                // 当前时间在12-18点之间，选择下午
                timeSlotCheckBoxes.get("下午").setSelected(true);
            } else if (currentTime.isBefore(LocalTime.of(22, 0))) {
                // 当前时间在18-22点之间，选择晚上
                timeSlotCheckBoxes.get("晚上").setSelected(true);
            } else {
                // 22点之后，默认选择明天的上午
                // 这时候应该切换到明天并选择上午
                if (dateComboBox.getItemCount() > 1) {
                    dateComboBox.setSelectedIndex(1); // 选择明天
                }
                timeSlotCheckBoxes.get("上午").setSelected(true);
            }
        } else {
            // 如果选择的是明天或其他日期，默认选择上午
            timeSlotCheckBoxes.get("上午").setSelected(true);
        }
    }

    /**
     * 刷新数据 - 供外部调用
     */
    public void refreshData() {
        if (isFloorSelectionView) {
            loadFloorSelection();
        } else {
            updateSeatAvailability();
        }
    }
}
